package kml;

/**
 * @author pangdonghao
 * @email pangdonghao@foxmail.com
 * @date 2020/12/7
 */

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/*
 *  DOM4J类
     DOM4J定义了几个Java类。以下是最常见的类：
     Document - 表示整个XML文档。文档Document对象是通常被称为DOM树。
     Element - 表示一个XML元素。 Element对象有方法来操作其子元素，它的文本，属性和名称空间。
     Attribute - 表示元素的属性。属性有方法来获取和设置属性的值。它有父节点和属性类型。
     Node - 代表元素，属性或处理指令

    常见DOM4J的方法
     当使用DOM4J，还有经常用到的几种方法：
     SAXReader.read(xmlSource)() - 构建XML源的DOM4J文档。
     Document.getRootElement() - 得到的XML的根元素。
     Element.node(index) - 获得在元素特定索引XML节点。
     Element.attributes() - 获取一个元素的所有属性。
     Node.valueOf(@Name) - 得到元件的给定名称的属性的值。
 *
 * */

public class ParseXml {

    public static void main(String[] args) throws Exception {
        Document document = readXML("C:\\code\\地图\\jd-gis-web\\public\\data\\国家边界线.kml");
        Element rootElement = document.getRootElement();
        handle(rootElement);
        writer(document,"D:\\test.kml");
    }


    public static void handle(Element node){
        //当前节点的名称、文本内容和属性
        if(node.getName().equals("coordinates")){
            System.out.println("--------------------");

            System.out.println("当前节点名称："+node.getName());//当前节点名称
            String[] s = node.getTextTrim().split(" ");
            if(s.length>20){
                List<double[]> doubles = dataThinning(s);
                StringBuilder stringBuilder = new StringBuilder();
                doubles.forEach((e) -> {
                    stringBuilder.append(e[0]).append(",").append(e[1]).append(" ");
                });
                node.setText(stringBuilder.toString());
            }
        }
        //递归遍历当前节点所有的子节点
        List<Element> listElement=node.elements();//所有一级子节点的list
        for(Element e:listElement){//遍历所有一级子节点
            handle(e);//递归
        }
    }

    public static Document readXML(String fileName) throws Exception {
        // 创建saxReader对象
        SAXReader reader = new SAXReader();
        // 通过read方法读取一个文件 转换成Document对象
        Document document = reader.read(new File(fileName));
        return document;
    }


    /**
     * 把document对象写入新的文件
     *
     * @param document
     * @throws Exception
     */
    public static void writer(Document document,String fileName) throws Exception {
        // 紧凑的格式
        // OutputFormat format = OutputFormat.createCompactFormat();
        // 排版缩进的格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        // 设置编码
        format.setEncoding("UTF-8");
        // 创建XMLWriter对象,指定了写出文件及编码格式
        // XMLWriter writer = new XMLWriter(new FileWriter(new
        // File("src//a.xml")),format);
        XMLWriter writer = new XMLWriter(
                new OutputStreamWriter(new FileOutputStream(new File(fileName)), "UTF-8"), format);
        // 写入
        writer.write(document);
        // 立即写入
        writer.flush();
        // 关闭操作
        writer.close();
    }


    /**
     * 抽稀
     * @param s
     * @return
     */
    public static List<double[]> dataThinning(String[] s){
        List<double[]> points = new ArrayList<>();
        List<double[]> points1 = new ArrayList<>();
        List<double[]> points2 = new ArrayList<>();
        for (String s1: s){
            String[] split = s1.split(",");
            double[] doubles = new double[2];
            doubles[0]= Double.parseDouble(split[0]);
            doubles[1]= Double.parseDouble(split[1]);
            points.add(doubles);
            if(points.size()< s.length/2){
                points1.add(doubles);
            }else {
                points2.add(doubles);
            }
        }
        List<double[]> reduced = DataThinning.douglasPeucker(points1, 1000);
        List<double[]> reduced2 = DataThinning.douglasPeucker(points2, 1000);
        try{
            if(reduced != null && reduced2 != null) {
                System.out.println("抽稀前大小：" + points.size());
                System.out.println("抽稀后大小：" + reduced.size());
                reduced.addAll(reduced2);
                return reduced;
            }
        }catch (Exception e){
            System.out.println("reduced: " + reduced);
            System.out.println("reduced2: " + reduced2);
        }
        return points;
    }
}
